package com.hwtx.form.domain.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.hwtx.form.persistence.entity.ApiDef;
import com.hwtx.form.persistence.entity.SysTenants;
import com.hwtx.form.persistence.mapper.SysTenantsMapper;
import com.hwtx.form.util.FormUtil;
import com.hwtx.form.util.JacksonUtil;
import io.geekidea.boot.framework.exception.BusinessException;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TenantsService {
    public static final String TENANTS_KEYS = "tenants_keys";
    public static final String TENANTS_ROLES = "tenants_roles";
    public static final String TENANTS_DB_FIELD_MAPPING = "tenants_db_field_mapping";
    public static final String TENANTS_GET_KEY_VALUE_SERVICE = "tenants_get_key_value_service";

    public static final String tenantsTableAndField = "tenantsTableAndField";
    @Resource
    private SysTenantsMapper sysTenantsMapper;
    @Resource
    private CommonApiInvoker commonApiInvoker;

    @Cacheable(value = tenantsTableAndField, key = "#table")
    public String getTenantTableField(String table) {
        LambdaQueryWrapper<SysTenants> wrapper = new LambdaQueryWrapper<>();
        SysTenants sysTenants = sysTenantsMapper.selectOne(wrapper.eq(SysTenants::getTKey, TENANTS_DB_FIELD_MAPPING));
        if (sysTenants == null || StringUtils.isEmpty(sysTenants.getTValue())) {
            return null;
        }
        Map<String, Object> mapping = JacksonUtil.json2Map(sysTenants.getTValue());
        if (mapping.get(table) != null) {
            return mapping.get(table).toString();
        }
        return null;
    }

    public String getTenantCode(List<Long> roleIds, Long userId) {
        LambdaQueryWrapper<SysTenants> wrapper = new LambdaQueryWrapper<>();
        SysTenants sysTenants = sysTenantsMapper.selectOne(wrapper.eq(SysTenants::getTKey, TENANTS_ROLES));
        if (sysTenants == null) {
            return null;
        }
        String tRoleIds = sysTenants.getTValue();
        if (StringUtils.isEmpty(tRoleIds)) {
            return null;
        }
        List<Long> tenantRoleIds = JacksonUtil.json2Array(tRoleIds, new TypeReference<>() {
        });
        roleIds.retainAll(tenantRoleIds);
        if (roleIds.isEmpty()) {
            return null;
        }
        wrapper.clear();
        sysTenants = sysTenantsMapper.selectOne(wrapper.eq(SysTenants::getTKey, TENANTS_GET_KEY_VALUE_SERVICE));
        if (sysTenants == null || StringUtils.isEmpty(sysTenants.getTValue())) {
            throw new BusinessException("租户信息未配置，请配置租户标识获取服务");
        }
        Map<String, Object> parameters = new HashMap<>();
        ApiDef apiDef = FormUtil.getApiDef(sysTenants.getTValue());
        List<String> paramInfos = CommonApiInvoker.getInputParamNames(apiDef);
        if (paramInfos.size() != 1) {
            throw new BusinessException("租户标识获取服务参数数量需要为1,serviceCode = " + sysTenants.getTKey());
        }
        parameters.put(paramInfos.getFirst(), userId);
        CommonApiInvoker.InvokeData invokeData = commonApiInvoker.invokeApiNoCareTest(apiDef, parameters, null);
        if (invokeData == null) {
            throw new BusinessException("租户标识获取服务调用失败,serviceCode = " + sysTenants.getTKey());
        }
        if (invokeData.getRet() != null) {
            if (CollectionUtils.isEmpty(invokeData.getRet())) {
                return null;
            }
            List<String> outputParams = CommonApiInvoker.getOutputParamNames(apiDef);
            if (CollectionUtils.isNotEmpty(outputParams)) {
                Object retObj = invokeData.getRet().getFirst().get(outputParams.getFirst());
                if (retObj != null) {
                    return retObj.toString();
                }
            }
            Object retData = invokeData.getRetData();
            if (retData != null) {
                return retData.toString();
            }
        }
        return null;
    }
}
